<?php

/***  DOCUMENTATION LAYER

Klenwell Database Object Class

Name: Kdbo
Last Update: Sep 2007
Author: Tom at klenwell@gmail.com

DESCRIPTION
  A wrapper for ADOdbLite

METHODS
  MAGIC
  Kdbo($debug=0, $oid=null)             *php 4 constructor*
  __construct($debug, $oid)             *php 5 constructor*
  __destruct()  
  
  PUBLIC
  connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
  quick_connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
  exec($sql, $DATA_BIND=false)
  get_insert_id()
  insert_array($table, $ARRAY, $check_cols=0)
  update_array($table, $ARRAY, $key_col, $key_val, $check_cols=0)
  close()
  
  print_d($message, $color='c33')
  print_r()
  dump()
  
  PRIVATE
  _load_adodb_lite($type)
  _single_connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
  _check_cxn_settings()
  
  _set_session_data()
  _get_session_data()
  _has_session_data()
  _set_filename()
  _set_dirpath()
  
  
USAGE
  $Dbo = new Kdbo('mysql', $debug=1);
  $Dbo->connect($db_name, $db_user, $db_pass, $db_host);
  $insert_id = $Dbo->insert_array($table, $ARRAY, $check_cols=0)

  
NOTES
  ADOdbLite Docs: http://adodblite.sourceforge.net/howtoinstall.php
  ADODB Manual: http://phplens.com/lens/adodb/docs-adodb.htm#connect 
  

______________________________________________________________________________*/

// Load File of Base Class
$base_fname = 'class.abstract.php';
#$base_dirpath = dirname(__FILE__) . DIRECTORY_SEPARATOR;
#require_once($base_dirpath . $base_fname);


// Class
/*____________________________________________________________________________*/
class Kdbo
{
/* PUBLIC PROPERTIES */
var $debug = 0;
var $class_name = __CLASS__;
var $oid = '';
var $DS = DIRECTORY_SEPARATOR;

// objects
var $Ado = 0;     // ADODB

// props
var $adodb_classpath = 'adodb_lite/adodb.inc.php';
var $adodb_path = '';

// db settings
var $db_name = '';
var $db_user = '';
var $db_pass = '';
var $db_host = 'localhost';

/* PRIVATE PROPERTIES */
var $_filename = '';
var $_dirpath = '';


/* ** MAGIC METHODS ** */
// php4 constructor
function Kdbo($type='mysql', $debug=0)
{
  $this->__construct($type, $debug);
  register_shutdown_function( array($this, '__destruct') );
}
// END constructor

// php5 constructor
function __construct($type='mysql', $debug=0, $adodb_path=null)
{
  // default
  $this->debug = $debug;
  $this->oid = $this->class_name . "_$type";
  $this->_set_filename();
  $this->_set_dirpath();
  
  // create ADOdbLite object
  $this->adodb_path = dirname($this->_dirpath) . "/php_ceo/ext_oss/" . $this->adodb_classpath;
  if ( !is_null($adodb_path) ) $this->adodb_path = $adodb_path;
  $this->type = $type;
  $this->_load_adodb_lite($this->type);
  
  // debug
  if ( $this->debug ) $this->print_d('debugging is active for oid ' . $this->oid);
  if ( $this->debug ) $this->print_d('constructor complete for class ' . __CLASS__);
}
// END constructor

// destructor
function __destruct()
{
  if ( $this->debug ) $this->print_d("destroying class {$this->class_name} (oid: {$this->oid})");
}
// END destructor



/* ** PUBLIC METHODS ** */
// method: connect to db
function connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
{
  if ( $this->debug ) $this->print_d("connecting to db [$db_name]");
  
  // configure settings
  $this->db_name = ( !is_null($db_name) ) ? $db_name : $this->db_name;
  $this->db_user = ( !is_null($db_user) ) ? $db_user : $this->db_user;
  $this->db_pass = ( !is_null($db_pass) ) ? $db_pass : $this->db_pass;
  $this->db_host = ( !is_null($db_host) ) ? $db_host : $this->db_host; 
  if ( is_null($flags) ) $flags = 2;
  
  // check settings
  if ( !$this->_check_cxn_settings() ) return 0;
  
  if ( !$this->Ado->Connect("$this->db_host", "$this->db_user", "$this->db_pass", "$this->db_name") )
  {
    trigger_error("failed to connect to db [$db_name]", E_USER_WARNING);
    return 0;
  }
  
  return 1;
}
// END method


// method: connect to db
function quick_connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
{
  if ( $this->debug ) $this->print_d("connecting to db [$db_name]");
  $this->Ado = $this->_load_adodb_lite($db_name, $db_user, $db_pass, $db_host, $flags);
  return;
}
// END method


// method: execute sql
function exec($sql, $DATA_BIND=false)
{
  $RecordSet = 0;    // Result Object
  
  if ( $this->debug ) $this->print_d("exec query [$sql]");

  // sanity check
  if ( !$this->Ado )
  {
    trigger_error('DB connection not found &ndash; be sure to connect to db before executing SQL command');
    return 0;
  }

  // execute query
  $sql = trim($sql);
  if ( !$RecordSet = $this->Ado->Execute($sql, $DATA_BIND) )
  {
    trigger_error('query failed: ' . $this->Ado->ErrorMsg(), E_USER_WARNING);
    return 0;
  }
  
  return $RecordSet;
}
// END method


// method: get insert id
function get_insert_id()
{
  $id = 0;
  if ( $id = $this->Ado->Insert_ID() )
  {
    if ( $this->debug ) $this->print_d("insert id is $id");
  }
  else
  {
    if ( $this->debug ) $this->print_d("unable to retrieve insert id");
  }
  
  return $id;
}
// END method


// method: insert array
function insert_array($table, $ARRAY, $check_cols=0)
{
  if ( $this->debug ) $this->print_d(__FUNCTION__ . ' : inserting array [' . print_r($ARRAY,1) . ']');
  $insert_id = 0;   // return
  
  // internal vars
  $DATA_BIND = array();
  $RecordSet = 0;
  $sql = '';
  
  // sanity check
  if ( !$this->Ado )
  {
    trigger_error('DB connection not found &ndash; be sure to connect to db before executing SQL command');
    return 0;
  }
  
  // check col tables
  if ( $this->debug && $check_cols ) $this->print_d('check col in dev');
  
  // build query string
  $_insert_line = $_values_line = '';
  foreach ( $ARRAY as $_col => $_value )
  {
    // extend insert, values line
    $_insert_line .= "`$_col`, ";
    $_values_line .= "?, ";
    
    // add value to data binding array
    $DATA_BIND[] = $_value;
  }
  
  // trim insert superfluous comma from query strings
  $_insert_line = substr($_insert_line, 0, strrpos($_insert_line, ','));
  $_values_line = substr($_values_line, 0, strrpos($_values_line, ','));
  
  // SQL query
  $sql = <<<SQL
INSERT INTO `$table` ( $_insert_line )
VALUES ( $_values_line )	  
SQL;

  // exec query
  if ( $this->exec($sql, $DATA_BIND) )
  {
    $insert_id = $this->get_insert_id();
  }
  else
  {
    $insert_id = 0;
  }
  
  return $insert_id;
}
// END method


// method: update array
function update_array($table, $ARRAY, $key_col, $key_val, $check_cols=0)
{
  if ( $this->debug ) $this->print_d(__FUNCTION__ . ' : updating array [' . print_r($ARRAY,1) . "] where '$key_col' = $key_val");
  $updated_rows = FALSE;   // return
  
  // internal vars
  $DATA_BIND = array();
  $RecordSet = 0;
  $sql = '';
  
  // sanity check
  if ( !$this->Ado )
  {
    trigger_error('DB connection not found &ndash; be sure to connect to db before executing SQL command');
    return 0;
  }
  
  // check col tables
  if ( $this->debug && $check_cols ) $this->print_d('check col in dev');
  
  // build query string
  $_update_line = '';
  foreach ( $ARRAY as $_col => $_val )
  {
    // extend update link
    $_update_line .= "`$_col` = ?, ";
    
    // add value to data binding array
    $DATA_BIND[] = $_val;
  }
  
  // trim insert superfluous comma from query strings
  $_update_line = trim(substr($_update_line, 0, strrpos($_update_line, ',')));
  
  // SQL query
  $sql = <<<SQL
UPDATE `$table` 
SET $_update_line
WHERE `$key_col` = ?
SQL;

  // add key col to DATA BIND
  $DATA_BIND[] = $key_val;

  // exec query
  if ( $this->exec($sql, $DATA_BIND) )
  {
    $updated_rows = $this->Ado->Affected_Rows();
    if ( empty($updated_rows) ) $updated_rows = 0;
  }
  else
  {
    $updated_rows = FALSE;
  }
  
  return $updated_rows;
}
// END method


// method: close db
function close()
{
  $this->Ado->close();
  return;
}
// END method


// method: dev
function dev()
{
  $this->print_d(__FUNCTION__ . ' in dev');
  return;
}
// END method


// method: print_d
function print_d($message, $color='#c33')
{
  $_D = debug_backtrace();
  $f = basename($_D[0]['file']);
  $l = $_D[0]['line'];
  $loc = "{$f}:{$l}";
  $out = "<div style='line-height:1.5em; font-family:monospace; color:$color;'>$message <span style='color:#666;'>[$loc]</span></div>";
  $this->_DBG[] = "$loc -> " . strip_tags($message);
  echo $out;
  return;
}
// END method

// method: print_r
function print_r($Mixed)
{
  $return = htmlspecialchars(print_r($Mixed, 1));
  $return = "<pre>$return</pre>";
  return $return;
}
// END method

// method: dump
function dump()
{
  echo $this->print_r($this);
  return;
}
// END method



/* ** PRIVATE METHODS ** */
// method: dev
function _dev()
{
  $this->print_d(__FUNCTION__ . ' in dev');
  return;
}
// END method


// method: load ADOdbLite object
function _load_adodb_lite($type)
{
  // already loaded
  if ( is_object($this->Ado) ) 
  {
    if ( $this->debug ) $this->print_d('AdodbLite already loaded');
  }
  
  // new object
  else
  {  
    require_once($this->adodb_path);
    if ( $this->Ado = ADONewConnection($type) )
    {
      if ( $this->debug ) $this->print_d('AdodbLite now loaded');
    }
    else
    {
      trigger_error('unable to load AdodbLite object', E_USER_WARNING);
    }
  }

  $this->Ado->debug = ( $this->debug ) ? TRUE : FALSE;
  return;
}
// END method


// method: create object and connect
function _single_connect($db_name=null, $db_user=null, $db_pass=null, $db_host=null, $flags=null)
{
  // configure settings
  $this->db_name = ( !is_null($db_name) ) ? $db_name : $this->db_name;
  $this->db_user = ( !is_null($db_user) ) ? $db_user : $this->db_user;
  $this->db_pass = ( !is_null($db_pass) ) ? $db_pass : $this->db_pass;
  $this->db_host = ( !is_null($db_host) ) ? $db_host : $this->db_host; 
  if ( is_null($flags) ) $flags = 2;
  
  // check settings
  if ( !$this->_check_cxn_settings() ) return 0;

  // New ADO Object
  if ( !is_object($Ado) )
  {
    // Create New Object
    $_du = urlencode($this->db_user);
    $_dp = urlencode($this->db_pass);
    $_dsn = "mysql://{$_du}:{$_dp}@{$this->db_host}/{$this->db_name}?clientflags=$flags";
    if ( !$Ado =& ADONewConnection($_dsn) ) trigger_error('unable to connect to database [' . $this->db_name . ']', E_USER_WARNING);
  }

  // Retrieve Existing Object
  else
  {
    // New Connection
    if ( !$Ado->IsConnected() )
    {
      if ( !$Ado->Connect($this->db_host, $this->db_user, $this->db_pass, $this->db_name) ) 
      {
        trigger_error('unable to connect to database [' . $this->db_name . ']', E_USER_WARNING);
      }
      $Ado->db_name = $this->db_name;
    }

    // Existing Connection (check db name)
    elseif ( $this->db_name != $Ado->db_name )
    {
      $Ado->SelectDB($this->db_name);
      $Ado->db_name = $this->db_name;
    }
  }
  
  $Ado->debug = ( $this->debug ) ? TRUE : FALSE;
  return $Ado;
}
// END method


function _check_cxn_settings()
{
  if ( empty($this->db_name) )
  {
    trigger_error('db name not set');
    return 0;
  }
  
  if ( empty($this->db_user) )
  {
    trigger_error('db user not set');
    return 0;
  }
  
  if ( empty($this->db_pass) )
  {
    trigger_error('db pass not set');
    return 0;
  }
  
  if ( empty($this->db_host) )
  {
    trigger_error('db host not set');
    return 0;
  }
  
  return 1;
}
// END method



// method: _set_session_data
function _set_session_data()
{
  // initialize session
  if ( !session_id() ) session_start(); 
  $_SESSION[$this->oid] = array();
  
  // add session data here
  
  return;
}
// END method

// method: get session data
function _get_session_data()
{
  // initialize session
  if ( !$this->_has_session_data() ) return; 
    
  // retrieve session variables
  // $this->var = $_SESSION[$this->oid]['var'];
  
  return;
}
// END method

// method: has session data
function _has_session_data()
{
  // initialize session
  if ( !session_id() ) session_start(); 
    
  // retrieve session variables
  if ( empty($_SESSION[$this->oid]) ) return 0;
  else return 1;
}
// END method

function _set_filename() { $this->_filename = basename(__FILE__); }
function _set_dirpath() { $this->_dirpath = dirname(__FILE__) . $this->DS; }

} // end class
/*____________________________________________________________________________*/

?>
